using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using JGSY.CMS.LowCode.Platform.Application.Interfaces;
using JGSY.CMS.LowCode.Platform.Application.DTOs;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Services
{
    /// <summary>
    /// 综合日志管理服务接口
    /// 统一管理所有类型的日志记录和查询
    /// </summary>
    public interface IComprehensiveLogService
    {
        #region 异常日志
        /// <summary>
        /// 记录异常日志
        /// </summary>
        Task<long> LogExceptionAsync(Exception exception, LogContext? context = null);

        /// <summary>
        /// 记录严重异常
        /// </summary>
        Task<long> LogCriticalExceptionAsync(Exception exception, LogContext context);
        #endregion

        #region 操作日志
        /// <summary>
        /// 记录操作日志
        /// </summary>
        Task<long> LogOperationAsync(string operation, LogContext? context = null);

        /// <summary>
        /// 记录用户操作
        /// </summary>
        Task<long> LogUserOperationAsync(string operation, string userId, LogContext? context = null);
        #endregion

        #region 安全日志
        /// <summary>
        /// 记录安全事件
        /// </summary>
        Task<long> LogSecurityEventAsync(string eventType, string message, LogContext? context = null);

        /// <summary>
        /// 记录登录事件
        /// </summary>
        Task<long> LogLoginEventAsync(string userId, bool success, string? reason = null, LogContext? context = null);

        /// <summary>
        /// 记录权限违规
        /// </summary>
        Task<long> LogPermissionViolationAsync(string userId, string permission, string resource, LogContext? context = null);
        #endregion

        #region 审计日志
        /// <summary>
        /// 记录审计日志
        /// </summary>
        Task<long> LogAuditAsync(string action, string resource, LogContext? context = null);

        /// <summary>
        /// 记录数据变更审计
        /// </summary>
        Task<long> LogDataChangeAuditAsync(string entity, string entityId, string action, object? oldValue = null, object? newValue = null, LogContext? context = null);
        #endregion

        #region 控制台日志
        /// <summary>
        /// 记录控制台信息日志（仅控制台输出，不存数据库）
        /// </summary>
        void LogConsoleInfo(string message, LogContext? context = null);

        /// <summary>
        /// 记录控制台警告日志（仅控制台输出，不存数据库）
        /// </summary>
        void LogConsoleWarning(string message, LogContext? context = null);

        /// <summary>
        /// 记录控制台错误日志（仅控制台输出，不存数据库）
        /// </summary>
        void LogConsoleError(string message, Exception? exception = null, LogContext? context = null);

        /// <summary>
        /// 记录控制台调试日志（仅控制台输出，不存数据库）
        /// </summary>
        void LogConsoleDebug(string message, LogContext? context = null);
        #endregion

        #region 批量操作
        /// <summary>
        /// 批量记录日志
        /// </summary>
        Task<int> LogBatchAsync(IEnumerable<BatchLogEntry> entries);
        #endregion

        #region 查询统计
        /// <summary>
        /// 获取综合日志统计
        /// </summary>
        Task<ComprehensiveLogStatistics> GetLogStatisticsAsync(DateTime? startTime = null, DateTime? endTime = null, string? tenantId = null);

        /// <summary>
        /// 搜索日志
        /// </summary>
        Task<LogSearchResult> SearchLogsAsync(LogSearchCriteria criteria);
        #endregion
    }

    /// <summary>
    /// 综合日志管理服务实现
    /// </summary>
    public class ComprehensiveLogService : IComprehensiveLogService
    {
        private readonly IExceptionLogAppService _exceptionLogService;
        private readonly IOperationLogAppService _operationLogService;
        private readonly ISecurityLogAppService _securityLogService;
        private readonly IEnhancedAuditService _auditService;
        private readonly ILogger<ComprehensiveLogService> _logger;

        public ComprehensiveLogService(
            IExceptionLogAppService exceptionLogService,
            IOperationLogAppService operationLogService,
            ISecurityLogAppService securityLogService,
            IEnhancedAuditService auditService,
            ILogger<ComprehensiveLogService> logger)
        {
            _exceptionLogService = exceptionLogService;
            _operationLogService = operationLogService;
            _securityLogService = securityLogService;
            _auditService = auditService;
            _logger = logger;
        }

        #region 异常日志实现
        /// <summary>
        /// 记录异常日志
        /// 将系统异常信息记录到日志系统，支持上下文关联和追踪
        /// </summary>
        /// <param name="exception">要记录的异常对象</param>
        /// <param name="context">日志上下文信息，包含追踪ID、用户信息等</param>
        /// <returns>记录的日志ID</returns>
        public async Task<long> LogExceptionAsync(Exception exception, LogContext? context = null)
        {
            try
            {
                return await _exceptionLogService.LogExceptionAsync(
                    exception,
                    context?.TraceId,
                    context?.CorrelationId,
                    context?.TenantId,
                    context?.UserId,
                    context?.RequestPath,
                    context?.HttpMethod,
                    context?.AdditionalData);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "记录异常日志时发生错误");
                return 0;
            }
        }

        /// <summary>
        /// 记录严重异常日志
        /// 专门用于记录系统关键异常，具备完整的上下文信息和严重级别标记
        /// </summary>
        /// <param name="exception">严重异常对象</param>
        /// <param name="context">完整的异常上下文信息</param>
        /// <returns>记录的日志ID</returns>
        public async Task<long> LogCriticalExceptionAsync(Exception exception, LogContext context)
        {
            try
            {
                var exceptionContext = new ExceptionContext
                {
                    TraceId = context.TraceId,
                    CorrelationId = context.CorrelationId,
                    TenantId = context.TenantId,
                    UserId = context.UserId,
                    UserName = context.UserName,
                    RequestPath = context.RequestPath,
                    HttpMethod = context.HttpMethod,
                    UserAgent = context.UserAgent,
                    IpAddress = context.IpAddress,
                    AdditionalData = context.AdditionalData
                };

                return await _exceptionLogService.LogCriticalExceptionAsync(exception, exceptionContext);
            }
            catch (Exception ex)
            {
                _logger.LogCritical(ex, "记录严重异常日志时发生错误");
                return 0;
            }
        }
        #endregion

        #region 操作日志实现
        public async Task<long> LogOperationAsync(string operation, LogContext? context = null)
        {
            try
            {
                return await _operationLogService.LogOperationAsync(
                    "Operation",
                    operation,
                    context?.Description,
                    context?.UserId,
                    context?.UserName,
                    context?.TenantId,
                    context?.CorrelationId,
                    context?.RequestPath,
                    context?.HttpMethod,
                    context?.Duration,
                    context?.Success ?? true,
                    context?.AdditionalData);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "记录操作日志时发生错误");
                return 0;
            }
        }

        public async Task<long> LogUserOperationAsync(string operation, string userId, LogContext? context = null)
        {
            try
            {
                var operationContext = new OperationContext
                {
                    OperationType = "UserOperation",
                    OperationName = operation,
                    Description = context?.Description,
                    UserId = userId,
                    UserName = context?.UserName,
                    TenantId = context?.TenantId,
                    CorrelationId = context?.CorrelationId,
                    TraceId = context?.TraceId,
                    RequestPath = context?.RequestPath,
                    HttpMethod = context?.HttpMethod,
                    IpAddress = context?.IpAddress,
                    UserAgent = context?.UserAgent,
                    Duration = context?.Duration,
                    Success = context?.Success ?? true,
                    AdditionalData = context?.AdditionalData
                };

                return await _operationLogService.LogUserOperationAsync(operationContext);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "记录用户操作日志时发生错误");
                return 0;
            }
        }
        #endregion

        #region 安全日志实现
        public async Task<long> LogSecurityEventAsync(string eventType, string message, LogContext? context = null)
        {
            try
            {
                return await _securityLogService.LogSecurityEventAsync(
                    eventType,
                    message,
                    context?.ThreatLevel,
                    context?.UserId,
                    context?.IpAddress,
                    context?.UserAgent,
                    context?.TenantId,
                    context?.CorrelationId,
                    context?.IsBlocked ?? false,
                    context?.AdditionalData);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "记录安全事件日志时发生错误");
                return 0;
            }
        }

        public async Task<long> LogLoginEventAsync(string userId, bool success, string? reason = null, LogContext? context = null)
        {
            try
            {
                var loginContext = new LoginSecurityContext
                {
                    UserId = userId,
                    UserName = context?.UserName,
                    LoginResult = success ? "Success" : "Failed",
                    FailureReason = reason,
                    IpAddress = context?.IpAddress,
                    UserAgent = context?.UserAgent,
                    TenantId = context?.TenantId,
                    CorrelationId = context?.CorrelationId,
                    AdditionalData = context?.AdditionalData
                };

                return await _securityLogService.LogLoginSecurityEventAsync(loginContext);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "记录登录事件日志时发生错误");
                return 0;
            }
        }

        public async Task<long> LogPermissionViolationAsync(string userId, string permission, string resource, LogContext? context = null)
        {
            try
            {
                var violationContext = new PermissionViolationContext
                {
                    UserId = userId,
                    UserName = context?.UserName,
                    RequiredPermission = permission,
                    AccessedResource = resource,
                    RequestPath = context?.RequestPath,
                    HttpMethod = context?.HttpMethod,
                    IpAddress = context?.IpAddress,
                    UserAgent = context?.UserAgent,
                    TenantId = context?.TenantId,
                    CorrelationId = context?.CorrelationId,
                    ViolationType = "Unauthorized",
                    AdditionalData = context?.AdditionalData
                };

                return await _securityLogService.LogPermissionViolationAsync(violationContext);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "记录权限违规日志时发生错误");
                return 0;
            }
        }
        #endregion

        #region 审计日志实现
        public async Task<long> LogAuditAsync(string action, string resource, LogContext? context = null)
        {
            try
            {
                var auditLog = await _auditService.LogBusinessOperationAsync(
                    context?.UserId ?? "System",
                    action,
                    $"{action} {resource}",
                    resource,
                    context?.RequestPath ?? "Unknown",
                    context?.AdditionalData,
                    context?.TenantId,
                    context?.CorrelationId);

                return auditLog.Id;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "记录审计日志时发生错误");
                return 0;
            }
        }

        public async Task<long> LogDataChangeAuditAsync(string entity, string entityId, string action, object? oldValue = null, object? newValue = null, LogContext? context = null)
        {
            try
            {
                var oldValues = oldValue != null ? new Dictionary<string, object> { ["data"] = oldValue } : null;
                var newValues = newValue != null ? new Dictionary<string, object> { ["data"] = newValue } : null;

                var auditLog = await _auditService.LogDataChangeAsync(
                    context?.UserId ?? "System",
                    entity,
                    entityId,
                    action,
                    oldValues,
                    newValues,
                    context?.TenantId,
                    context?.CorrelationId);

                return auditLog.Id;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "记录数据变更审计日志时发生错误");
                return 0;
            }
        }
        #endregion

        #region 控制台日志实现
        public void LogConsoleInfo(string message, LogContext? context = null)
        {
            var logMessage = FormatConsoleMessage("INFO", message, context);
            _logger.LogInformation(logMessage);
        }

        public void LogConsoleWarning(string message, LogContext? context = null)
        {
            var logMessage = FormatConsoleMessage("WARN", message, context);
            _logger.LogWarning(logMessage);
        }

        public void LogConsoleError(string message, Exception? exception = null, LogContext? context = null)
        {
            var logMessage = FormatConsoleMessage("ERROR", message, context);
            if (exception != null)
            {
                _logger.LogError(exception, logMessage);
            }
            else
            {
                _logger.LogError(logMessage);
            }
        }

        public void LogConsoleDebug(string message, LogContext? context = null)
        {
            var logMessage = FormatConsoleMessage("DEBUG", message, context);
            _logger.LogDebug(logMessage);
        }

        private string FormatConsoleMessage(string level, string message, LogContext? context)
        {
            var formattedMessage = $"[{level}] {message}";
            
            if (context != null)
            {
                var contextInfo = new List<string>();
                
                if (!string.IsNullOrEmpty(context.TraceId))
                    contextInfo.Add($"TraceId={context.TraceId}");
                
                if (!string.IsNullOrEmpty(context.CorrelationId))
                    contextInfo.Add($"CorrelationId={context.CorrelationId}");
                
                if (!string.IsNullOrEmpty(context.TenantId))
                    contextInfo.Add($"TenantId={context.TenantId}");
                
                if (!string.IsNullOrEmpty(context.UserId))
                    contextInfo.Add($"UserId={context.UserId}");

                if (contextInfo.Count > 0)
                {
                    formattedMessage += $" | {string.Join(", ", contextInfo)}";
                }
            }

            return formattedMessage;
        }
        #endregion

        #region 批量操作实现
        public async Task<int> LogBatchAsync(IEnumerable<BatchLogEntry> entries)
        {
            int totalProcessed = 0;

            try
            {
                var groupedEntries = entries.GroupBy(e => e.LogType);

                foreach (var group in groupedEntries)
                {
                    switch (group.Key)
                    {
                        case LogType.Exception:
                            totalProcessed += await ProcessExceptionLogs(group);
                            break;
                        case LogType.Operation:
                            totalProcessed += await ProcessOperationLogs(group);
                            break;
                        case LogType.Security:
                            totalProcessed += await ProcessSecurityLogs(group);
                            break;
                        case LogType.Audit:
                            totalProcessed += await ProcessAuditLogs(group);
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量记录日志时发生错误");
            }

            return totalProcessed;
        }

        private async Task<int> ProcessExceptionLogs(IEnumerable<BatchLogEntry> entries)
        {
            int count = 0;
            foreach (var entry in entries)
            {
                if (entry.Exception != null)
                {
                    await LogExceptionAsync(entry.Exception, entry.Context);
                    count++;
                }
            }
            return count;
        }

        private async Task<int> ProcessOperationLogs(IEnumerable<BatchLogEntry> entries)
        {
            var operations = entries.Select(e => new OperationContext
            {
                OperationType = e.OperationType ?? "BatchOperation",
                OperationName = e.Message,
                Description = e.Context?.Description,
                UserId = e.Context?.UserId,
                UserName = e.Context?.UserName,
                TenantId = e.Context?.TenantId,
                CorrelationId = e.Context?.CorrelationId,
                TraceId = e.Context?.TraceId,
                RequestPath = e.Context?.RequestPath,
                HttpMethod = e.Context?.HttpMethod,
                IpAddress = e.Context?.IpAddress,
                UserAgent = e.Context?.UserAgent,
                Duration = e.Context?.Duration,
                Success = e.Context?.Success ?? true,
                AdditionalData = e.Context?.AdditionalData,
                Timestamp = e.Timestamp
            });

            return await _operationLogService.LogBatchOperationsAsync(operations);
        }

        private async Task<int> ProcessSecurityLogs(IEnumerable<BatchLogEntry> entries)
        {
            var events = entries.Select(e => new SecurityEventContext
            {
                EventType = e.EventType ?? "BatchSecurityEvent",
                Message = e.Message,
                ThreatLevel = e.Context?.ThreatLevel,
                UserId = e.Context?.UserId,
                IpAddress = e.Context?.IpAddress,
                UserAgent = e.Context?.UserAgent,
                TenantId = e.Context?.TenantId,
                CorrelationId = e.Context?.CorrelationId,
                RequestPath = e.Context?.RequestPath,
                HttpMethod = e.Context?.HttpMethod,
                IsBlocked = e.Context?.IsBlocked ?? false,
                AdditionalData = e.Context?.AdditionalData,
                Timestamp = e.Timestamp
            });

            return await _securityLogService.LogBatchSecurityEventsAsync(events);
        }

        private async Task<int> ProcessAuditLogs(IEnumerable<BatchLogEntry> entries)
        {
            int count = 0;
            foreach (var entry in entries)
            {
                await LogAuditAsync(entry.ActionType ?? "BatchAudit", entry.ResourceType ?? "Unknown", entry.Context);
                count++;
            }
            return count;
        }
        #endregion

        #region 查询统计实现
        public async Task<ComprehensiveLogStatistics> GetLogStatisticsAsync(DateTime? startTime = null, DateTime? endTime = null, string? tenantId = null)
        {
            try
            {
                var statistics = new ComprehensiveLogStatistics();

                // 并行获取各类日志统计
                var tasks = new Task[]
                {
                    Task.Run(async () => 
                    {
                        try
                        {
                            statistics.ExceptionStatistics = await _exceptionLogService.GetExceptionStatisticsAsync(tenantId, startTime, endTime);
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(ex, "获取异常日志统计时发生错误");
                        }
                    }),
                    Task.Run(async () => 
                    {
                        try
                        {
                            statistics.OperationStatistics = await _operationLogService.GetOperationStatisticsAsync(tenantId, null, startTime, endTime);
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(ex, "获取操作日志统计时发生错误");
                        }
                    }),
                    Task.Run(async () => 
                    {
                        try
                        {
                            statistics.SecurityStatistics = await _securityLogService.GetSecurityThreatStatisticsAsync(tenantId, startTime, endTime);
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(ex, "获取安全日志统计时发生错误");
                        }
                    })
                };

                await Task.WhenAll(tasks);

                return statistics;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取综合日志统计时发生错误");
                return new ComprehensiveLogStatistics();
            }
        }

        public async Task<LogSearchResult> SearchLogsAsync(LogSearchCriteria criteria)
        {
            try
            {
                var result = new LogSearchResult();

                if (criteria.IncludeExceptionLogs)
                {
                    var (items, total) = await _exceptionLogService.GetExceptionLogsAsync(
                        criteria.TenantId,
                        criteria.ExceptionLevel,
                        criteria.StartTime,
                        criteria.EndTime,
                        criteria.PageIndex,
                        criteria.PageSize);
                    
                    result.ExceptionLogs = items;
                    result.TotalExceptionLogs = total;
                }

                if (criteria.IncludeOperationLogs)
                {
                    var (items, total) = await _operationLogService.GetOperationLogsAsync(
                        criteria.TenantId,
                        criteria.UserId,
                        criteria.OperationType,
                        criteria.StartTime,
                        criteria.EndTime,
                        criteria.Success,
                        criteria.PageIndex,
                        criteria.PageSize);
                    
                    result.OperationLogs = items;
                    result.TotalOperationLogs = total;
                }

                if (criteria.IncludeSecurityLogs)
                {
                    var (items, total) = await _securityLogService.GetSecurityLogsAsync(
                        criteria.TenantId,
                        criteria.SecurityEventType,
                        criteria.ThreatLevel,
                        criteria.UserId,
                        criteria.IpAddress,
                        criteria.StartTime,
                        criteria.EndTime,
                        criteria.IsBlocked,
                        criteria.PageIndex,
                        criteria.PageSize);
                    
                    result.SecurityLogs = items;
                    result.TotalSecurityLogs = total;
                }

                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "搜索日志时发生错误");
                return new LogSearchResult();
            }
        }
        #endregion
    }

    #region 辅助类和枚举
    /// <summary>
    /// 日志上下文信息
    /// </summary>
    public class LogContext
    {
        public string? TraceId { get; set; }
        public string? CorrelationId { get; set; }
        public string? TenantId { get; set; }
        public string? UserId { get; set; }
        public string? UserName { get; set; }
        public string? RequestPath { get; set; }
        public string? HttpMethod { get; set; }
        public string? IpAddress { get; set; }
        public string? UserAgent { get; set; }
        public string? Description { get; set; }
        public string? ThreatLevel { get; set; }
        public bool? Success { get; set; }
        public long? Duration { get; set; }
        public bool? IsBlocked { get; set; }
        public Dictionary<string, object>? AdditionalData { get; set; }
    }

    /// <summary>
    /// 批量日志条目
    /// </summary>
    public class BatchLogEntry
    {
        public LogType LogType { get; set; }
        public string Message { get; set; } = string.Empty;
        public string? OperationType { get; set; }
        public string? ActionType { get; set; }
        public string? ResourceType { get; set; }
        public string? EventType { get; set; }
        public Exception? Exception { get; set; }
        public LogContext? Context { get; set; }
        public DateTime Timestamp { get; set; } = DateTime.UtcNow;
    }

    /// <summary>
    /// 日志类型枚举
    /// </summary>
    public enum LogType
    {
        Exception,
        Operation,
        Security,
        Audit,
        Console
    }

    /// <summary>
    /// 综合日志统计信息
    /// </summary>
    public class ComprehensiveLogStatistics
    {
        public ExceptionStatistics? ExceptionStatistics { get; set; }
        public OperationStatistics? OperationStatistics { get; set; }
        public SecurityThreatStatistics? SecurityStatistics { get; set; }
        public DateTime StatisticsDate { get; set; } = DateTime.UtcNow;
    }

    /// <summary>
    /// 日志搜索条件
    /// </summary>
    public class LogSearchCriteria
    {
        public string? TenantId { get; set; }
        public string? UserId { get; set; }
        public string? OperationType { get; set; }
        public string? ExceptionLevel { get; set; }
        public string? SecurityEventType { get; set; }
        public string? ThreatLevel { get; set; }
        public string? IpAddress { get; set; }
        public DateTime? StartTime { get; set; }
        public DateTime? EndTime { get; set; }
        public bool? Success { get; set; }
        public bool? IsBlocked { get; set; }
        public bool IncludeExceptionLogs { get; set; } = true;
        public bool IncludeOperationLogs { get; set; } = true;
        public bool IncludeSecurityLogs { get; set; } = true;
        public bool IncludeAuditLogs { get; set; } = true;
        public int PageIndex { get; set; } = 1;
        public int PageSize { get; set; } = 20;
    }

    /// <summary>
    /// 日志搜索结果
    /// </summary>
    public class LogSearchResult
    {
        public List<ExceptionLogDto>? ExceptionLogs { get; set; }
        public List<OperationLogDto>? OperationLogs { get; set; }
        public List<SecurityLogDto>? SecurityLogs { get; set; }
        public List<AuditLogDto>? AuditLogs { get; set; }
        public int TotalExceptionLogs { get; set; }
        public int TotalOperationLogs { get; set; }
        public int TotalSecurityLogs { get; set; }
        public int TotalAuditLogs { get; set; }
    }
    #endregion
}
